package com.lmq.innerclasses;// innerclasses/Sequence.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Holds a sequence of Objects

interface Selector {
  boolean end();
  Object current();
  void next();
}

public class Sequence {
  private Object[] items;
  private int next = 0;
  public Sequence(int size) {
    items = new Object[size];
  }
  public void add(Object x) {
    if(next < items.length)
      items[next++] = x;
  }
  private class SequenceSelector implements Selector {
    private int i = 0;
    @Override
    public boolean end() { return i == items.length; }
    @Override
    public Object current() { return items[i]; }
    @Override
    public void next() { if(i < items.length) i++; }
  }
  public Selector selector() {
    return new SequenceSelector();
  }
  public static void main(String[] args) {
    Sequence sequence = new Sequence(10);
    for(int i = 0; i < 10; i++)
      sequence.add(Integer.toString(i));
    Selector selector = sequence.selector();
    while(!selector.end()) {
      System.out.print(selector.current() + " ");
      selector.next();
    }
  }
}
/* Output:
0 1 2 3 4 5 6 7 8 9
*/
/**
 * The Sequence is a fixed-sized array of Object with a class wrapped around it
 * You call add() to add a new Object to the end of the sequence(if there's room left).
 * To fetch each of the objects in a Sequence, there's an interface called Selector.
 * This is an example of the Iterator design pattern you shall learn more about in the Collections chapter.A
 * Selector tell you whether you're at the end(), accesses the current() object, and moves to the next() object in the Sequence.
 * Because Selector is an interface, other classes can implement the interface in their own ways, and
 * other methods can take the interface as an argument, to create more general-purpose code.
 * Here, the SequenceSelector is a private class that provides Selector functionality.In main(), you
 * see the creation of Sequence, followed by the additon of a number of String objects.
 * you see the creation of a Sequence, followed by the addition of a number of String objects.Then,
 * a Selector is produce with a call to selector(), and this is used to move through the Sequence and select eahc item.
 * At first, the creation of SequenceSelector looks like just another inner class
 * But examine it closely.Note that each of the methods--end(), current, and next()
 * refers ot items, a reference that isn't part of SequenceSelector, but is instead a private field in the enclosing class.However,the
 * inner class can access methods and fields from the enclosing class as if it owned them.This turns out to be very convenient, as you see in the preceding example.
 * So an inner class has automatic access to the members of the enclosing class.how
 * can this happen?The inner class secretly captures a reference to the particular object of the enclosing class that was repsonsible for creating it.
 * Then, when you refer to a member of the enclosing class, that reference is used to select that member.Fortunately, the compiler takes care of all these details for you, but now
 * you see that an object of an inner class can be created only in association with an object of the enclosing class(when, as you shall see, the inner class is non-static).
 * Construction of the inner-class object requires the reference to the object of the enclosing class.
 * and the compiler will complain if it can not access taht refence.Most of the time this occurs without any intervention on
 * the part of the programmer.
 *
 * Using .this and .new
 * To produce the reference to the outer-class object,you name
 * the outer class followed by a dot and this. This resulting reference is automatically the correct type, known and
 * checked at compile time, so there is no runtime overhead.Here's how to use .this:
 *
 *
 */
